#ifndef _KERNEL_H_
#define _KERNEL_H_

typedef enum {
    code_segment = 0,
    data_segment,
    stack_segment,
} seg_type;

typedef struct  {
    uint16_t SegLength;
    uint16_t SegBaseLow;
    uint8_t SegBaseHighL;
    uint8_t SegAtt1;
    uint8_t SegAtt2;
    uint8_t SegBaseHighH;
} SegDescriptor;

typedef struct {
    uint16_t OffsetL;
    uint16_t Segment;
    uint16_t IntAttr;
    uint16_t OffsetH;
} IntDescriptor;

#define MEM_TYPE_UNKNOWN                0
#define MEM_TYPE_USABLE                 1
#define MEM_TYPE_LOCKED                 2
#define MEM_TYPE_ACPI                   3
#define MEM_TYPE_NVS                    4
#define MEM_TYPE_RESERVED               5

typedef struct {
    union {
        unsigned long addr32;
        unsigned long long addr64;
        } addr;
    union {
        unsigned long length32;
        unsigned long long length64;
        } length;
    unsigned int type;
} _PACK_ memoryframe;

typedef struct {

    void * pmem;
    size_t size;
    int flag;
    void * bitmap;
    void * ptrlist;
    int bitmaplow;
    int bitmaphigh;
} mem_part_pool;

typedef void (* EOI_FUNC)();

#define SEG_GLOBAL_FLAT_SELECTOR        0x0008

#define IA_80x86_MI_BASE_NUM            0x20

#define ERROR                           (-1)
#define OK                              0

/* meminit.c */

void w_to_m(char c, int realptr);

char r_from_m(int realptr);

void write_to_real(void * p, size_t l, int realp);

void read_from_real(void * p, size_t l, int realp);

void loadgdt(int * base_addr, int * limit);

void setgdt(int base_addr, int limit);

int createSegment(int segindex, int base_addr, int limit, seg_type stype);

void init_gdt();

short int GetCurrentCodeSeg();

void init_mem();

/* interrupt.c */

void loadidt(int * base_addr, int * limit);

void setidt(int base_addr, int limit);

int installInterrupt(char int_num, int offset, short segindex, int paramcount);

void install_vitual_int(char int_num, int ip);

void init_int();

/* hardware.c */

void hardware_init();

/* memlib.c */

void mem_part_init();

mem_part_pool * mem_part_pool_create(void * base, size_t size, int flag, mem_part_pool * bfr);

#define out_b(addr, value)      asm __volatile__ ("movw %0, %%dx\n\tmovb %1, %%al\n\toutb %%al, %%dx\n\t"::"i"((addr)),"r"((value)):"%eax","%edx")
#define out_w(addr, value)      asm __volatile__ ("movw %0, %%dx\n\tmovw %1, %%ax\n\toutw %%ax, %%dx\n\t"::"i"((addr)),"r"((value)):"%eax","%edx")
#define out_dw(addr, value)     asm __volatile__ ("movw %0, %%dx\n\tmovl %1, %%eax\n\toutl %%eax, %%dx\n\t"::"i"((addr)),"r"((value)):"%eax","%edx")

#define in_b(addr, value)      asm __volatile__ ("movw %1, %%dx\n\tinb %%dx, %%al\n\tmovb %%al, %0\n\t":"=r"((value)):"i"((addr)):"%eax","%edx")
#define in_w(addr, value)      asm __volatile__ ("movw %1, %%dx\n\tinw %%dx, %%ax\n\tmovw %%ax, %0\n\t":"=r"((value)):"i"((addr)):"%eax","%edx")
#define in_dw(addr, value)     asm __volatile__ ("movw %1, %%dx\n\tinl %%dx, %%eax\n\tmovl %%eax, %0\n\t":"=r"((value)):"i"((addr)):"%eax","%edx")

#define int_lock()              asm __volatile__ ("pushf\n\tcli\n\t")
#define int_unlock()            asm __volatile__ ("sti\n\tpopf\n\t")

#define int_reset()             asm __volatile__ ("sti\n\t")

#define asm_delay()             asm __volatile__ ("nop\n\tnop\n\tnop\n\tnop\n\t")

#endif _KERNEL_H_ /* end of _KERNEL_H_ */
